package com.zhi.syc.data_applist.services;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;

import androidx.core.content.ContextCompat;

import com.zhi.syc.data_applist.ASBuilder;
import com.zhi.syc.data_applist.beans.ASLocationInfoBean;
import com.zhi.syc.data_applist.logger.ASLogger;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class ASLocationInfo {
    private static final String TAG = "ASLocationInfo";

    private static ASLocationInfo instance = new ASLocationInfo();

    private static LocationManager mLocationManager;

    private static Location mLocation = null;

    private OnLocationDidFetchedListener mOnLocationDidFetchedListener;

    private Context mContext;

    private String mBestProvider = LocationManager.NETWORK_PROVIDER;

    public ASLocationInfo() {
    }

    public static ASLocationInfo getInstance() {
        return instance;
    }

    public static boolean init(Context context) {
        return ASLocationInfo.getInstance().initLocation(context);
    }

    public static boolean getLocationInfo(OnLocationDidFetchedListener onLocationDidFetchedListener) {
        return ASLocationInfo.getInstance().getLocation(onLocationDidFetchedListener);
    }

    public boolean initLocation(Context context) {
        this.mContext = context;
        if (context == null) {
            return false;
        }

        try {
            if (mLocationManager == null) {
                mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

                if (!mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                    // 返回开启GPS导航设置界面
                    return false;
                }

                // 判断GPS是否正常启动
                if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    // 返回开启GPS导航设置界面
                    return false;
                }

                // 为获取地理位置信息时设置查询条件
                mBestProvider = LocationManager.NETWORK_PROVIDER;//mLocationManager.getBestProvider(getCriteria(), true);

                List<String> providers = mLocationManager.getProviders(true);
                if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
                    //如果是Network
                    mBestProvider = LocationManager.NETWORK_PROVIDER;
                }

                // 获取位置信息
                // 如果不设置查询要求，getLastKnownLocation方法传人的参数为LocationManager.GPS_PROVIDER
                if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                        ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }

                Location location = mLocationManager.getLastKnownLocation(mBestProvider);
                mLocation = location;

                // 绑定监听，有4个参数
                // 参数1，设备：有GPS_PROVIDER和NETWORK_PROVIDER两种
                // 参数2，位置信息更新周期，单位毫秒
                // 参数3，位置变化最小距离：当位置距离变化超过此值时，将更新位置信息
                // 参数4，监听
                // 备注：参数2和3，如果参数3不为0，则以参数3为准；参数3为0，则通过时间来定时更新；两者为0，则随时刷新
            }

            // 监听状态
            mLocationManager.addGpsStatusListener(mListener);

            if (!mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                // 返回开启GPS导航设置界面
                return false;
            }

            // 判断GPS是否正常启动
            if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                // 返回开启GPS导航设置界面
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

    public boolean getLocation(OnLocationDidFetchedListener onLocationDidFetchedListener) {
        this.mOnLocationDidFetchedListener = onLocationDidFetchedListener;

        if (mLocationManager == null) {
            return false;
        }
        // 1秒更新一次，或最小位移变化超过1米更新一次；
        // 注意：此处更新准确度非常低，推荐在service里面启动一个Thread，在run中sleep(10000);然后执行handler.sendMessage(),更新位置
        if (ContextCompat.checkSelfPermission(this.mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this.mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }

        // 监听状态
        mLocationManager.addGpsStatusListener(mListener);

        ASLogger.d(getClass().getSimpleName(), "mBestProvider: " + mBestProvider);
        mLocationManager.requestLocationUpdates(mBestProvider, 3000, 1, mLocationListener);
        return true;
    }

    public OnLocationDidFetchedListener getmOnLocationDidFetchedListener() {
        return mOnLocationDidFetchedListener;
    }

    public void setmOnLocationDidFetchedListener(OnLocationDidFetchedListener mOnLocationDidFetchedListener) {
        this.mOnLocationDidFetchedListener = mOnLocationDidFetchedListener;
    }

    public void removeUpdateMonitor() {
        try {
            if (mLocationManager != null) {
                mLocationManager.removeUpdates(mLocationListener);
                mLocationManager.removeGpsStatusListener(mListener);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Criteria getCriteria() {
        Criteria criteria = new Criteria();
        // 设置定位精确度 Criteria.ACCURACY_COARSE比较粗略，Criteria.ACCURACY_FINE则比较精细
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        // 设置是否要求速度
        criteria.setSpeedRequired(false);
        // 设置是否允许运营商收费
        criteria.setCostAllowed(true);
        // 设置是否需要方位信息
        criteria.setBearingRequired(false);
        // 设置是否需要海拔信息
        criteria.setAltitudeRequired(false);
        // 设置对电源的需求
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        return criteria;
    }

    public Location getLocationInstance() {
        if (mLocation == null) {
            ASLogger.d("GPSUtils", "setLocationData: 获取当前位置信息为空");
            return null;
        }
        return mLocation;
    }

    public String getLocalProvince() {
        if (mLocation == null) {
            ASLogger.d("GPSUtils", "getLocalCity: 获取城市信息为空");
            return "";
        }

        String city = "";
        try {
            List<Address> result = getAddress(mLocation);
            if (result != null && result.size() > 0) {
                city = result.get(0).getAdminArea();//获取省份
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return city;
    }

    public String getLocalCity() {
        if (mLocation == null) {
            ASLogger.d("GPSUtils", "getLocalCity: 获取城市信息为空");
            return "";
        }

        String city = "";
        try {
            List<Address> result = getAddress(mLocation);
            if (result != null && result.size() > 0) {
                city = result.get(0).getLocality();//获取城市
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return city;
    }

    public String getSubLocality() {
        if (mLocation == null) {
            ASLogger.d("GPSUtils", "getLocalCity: 获取城市信息为空");
            return "";
        }

        String city = "";
        try {
            List<Address> result = getAddress(mLocation);
            if (result != null && result.size() > 0) {
                city = result.get(0).getSubLocality();//获取省份
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return city;
    }

    public String getFeatureName() {
        if (mLocation == null) {
            ASLogger.d("GPSUtils", "getLocalCity: 获取城市信息为空");
            return "";
        }
        String city = "";
        try {
            List<Address> result = getAddress(mLocation);
            if (result != null && result.size() > 0) {
                city = result.get(0).getFeatureName();//获取省份
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return city;
    }

    public String getDetailAddress() {
        if (mLocation == null) {
            ASLogger.d("GPSUtils", "getAddressStr: 获取详细地址信息为空");
            return "";
        }

        String address = "";
        try {

            List<Address> result = getAddress(mLocation);
            if (result != null && result.size() > 0) {
                address = result.get(0).getAddressLine(0);//获取详细地址
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return address;
    }

    private LocationListener mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            try {
                //位置信息变化时触发
                mLocation = location;
                ASLogger.d(TAG, "时间：" + location.getTime());
                ASLogger.d(TAG, "经度：" + location.getLongitude());
                ASLogger.d(TAG, "纬度：" + location.getLatitude());
                ASLogger.d(TAG, "海拔：" + location.getAltitude());
                ASLogger.d(TAG, "省份：" + getLocalCity());
                ASLogger.d(TAG, "城市：" + getLocalCity());

                ASLocationInfoBean locationInfoBean = new ASLocationInfoBean();
                locationInfoBean.setBorrowId("");
                locationInfoBean.setProvince(getLocalProvince());
                locationInfoBean.setCity(getLocalCity());
                locationInfoBean.setCounty(getSubLocality());
                locationInfoBean.setStreet(getFeatureName());
                locationInfoBean.setDetail(getDetailAddress());
                locationInfoBean.setLongitude(location.getLongitude() + "");
                locationInfoBean.setLatitude(location.getLatitude() + "");

                //上报
                if (mOnLocationDidFetchedListener != null) {
                    mOnLocationDidFetchedListener.onLocationDidFetched(locationInfoBean);
                }

                if (mLocationManager != null && mLocationListener != null) {
                    //mLocationManager.removeUpdates(mLocationListener);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            ASLogger.d(getClass().getSimpleName(), "onStatusChanged: " + provider);
            //GPS状态变化时触发
            switch (status) {
                // GPS状态为可见时
                case LocationProvider.AVAILABLE:
                    ASLogger.d(TAG, "当前GPS状态为可见状态");
                    break;
                // GPS状态为服务区外时
                case LocationProvider.OUT_OF_SERVICE:
                    ASLogger.d(TAG, "当前GPS状态为服务区外状态");
                    break;
                // GPS状态为暂停服务时
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
                    ASLogger.d(TAG, "当前GPS状态为暂停服务状态");
                    break;
            }
        }

        @Override
        public void onProviderEnabled(String provider) {
            ASLogger.d(getClass().getSimpleName(), "onProviderEnabled: " + provider);
            //GPS开启时触发
            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                mLocation = null;
                return;
            }
            try {
                Location location = mLocationManager.getLastKnownLocation(provider);
                mLocation = location;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
            mLocation = null;
            ASLogger.d(getClass().getSimpleName(), "onProviderDisabled: " + provider);
        }
    };

    private List<Address> getAddress(Location location) {
        List<Address> result = null;
        try {
            if (location != null) {
                Geocoder gc = new Geocoder(mContext, Locale.getDefault());
                result = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public Address getAccuracyAddress(Context context, Location location) {
        Address result = null;
        try {
            if (location != null && context != null) {
                Geocoder gc = new Geocoder(context, Locale.getDefault());
                List<Address> resultList = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
                if (resultList != null && resultList.size() > 0) {
                    result = resultList.get(0);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    GpsStatus.Listener mListener = event -> {
        switch (event) {
            // 第一次定位
            case GpsStatus.GPS_EVENT_FIRST_FIX:
                ASLogger.d(TAG, "第一次定位");
                break;
            // 卫星状态改变
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                ASLogger.d(TAG, "卫星状态改变");
                break;
            // 定位启动
            case GpsStatus.GPS_EVENT_STARTED:
                ASLogger.d(TAG, "定位启动");
                break;
            // 定位结束
            case GpsStatus.GPS_EVENT_STOPPED:
                ASLogger.d(TAG, "定位结束");
                break;
        }
    };

    public interface OnLocationDidFetchedListener {
        void onLocationDidFetched(ASLocationInfoBean locationInfoBean);
    }

}
